package jaux.tank.generator.jd.components;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;

import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

public abstract class JdLabeledInput<E,P> extends JPanel{
	
	public  static final int DEFAULT_LABEL_WIDTH = 100;
	
	public  static final int DEFAULT_INPUT_WIDTH = 200;

	public  static final int DEFAULT_HEIGHT = 28;
	
	private static final long serialVersionUID = 1L;

	private final String label;
	
	private final JLabel textLabel;
	
	private final JComponent input;
	
	
	private Set<Consumer<E>> changeHandlers = new HashSet<>();
	
	JdLabeledInput(String label, E defaultValue ) {
		this(label, defaultValue, null);
	}
	
	
	JdLabeledInput(String label, E defaultValue , P  params) {
		this.label = label;
		setLayout(new FlowLayout(FlowLayout.LEFT));
		textLabel = new JLabel(label);
		textLabel.setHorizontalAlignment(SwingConstants.RIGHT);
		add(textLabel);
		textLabel.setPreferredSize(new Dimension(DEFAULT_LABEL_WIDTH, DEFAULT_HEIGHT));
		beforeCreateInputComponent();
		input = createInputComponent(params);
		setInput(input);
		setValue(defaultValue);
		registerChangeHandler(this::fireChangeHandlers);
	}
	
	protected abstract void registerChangeHandler(Consumer<E> handler);


	protected void setInput(JComponent inputComp) {
		add(inputComp);
		inputComp.setPreferredSize(new Dimension(DEFAULT_INPUT_WIDTH, DEFAULT_HEIGHT));
		textLabel.setLabelFor(inputComp);
	}

	public void beforeCreateInputComponent() {}
	
	public void onChange(Consumer<E> handler) {
		this.changeHandlers.add(handler);
	}
	
	public void clearChangeHandlers() {
		this.changeHandlers.clear();
	}
	public void fireChangeHandlers(E value) {
		this.changeHandlers.forEach(h -> h.accept(value));
	}
	
	public abstract JComponent createInputComponent(P params);
	
	public abstract E getValue();
	
	public abstract void setValue(E value);
	
	public abstract void setEditable(boolean b) ;
	
	public String getLabel() {
		return this.label;
	}
	public void setLabelSize(int width, int height) {
		Dimension oldSize = textLabel.getPreferredSize();
		textLabel.setPreferredSize(new Dimension(width>0?width:oldSize.width, height>0?height:oldSize.height));
	}
	public void setInputComponentSize(int width, int height) {
		Dimension oldSize = input.getPreferredSize();
		input.setPreferredSize(new Dimension(width>0?width:oldSize.width, height>0?height:oldSize.height));
	}
}
